/*
 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package java.util;

import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;

/**
 * 
 * <p>一个类，为了遍历并且分割一个来源的元素。这些元素可以被一个spliterator覆盖，举个例子，
 * 一个数组，一个collection，一个io的channel或者一个工厂功能
 *
 * <p>一个spliterator可能独自地遍历元素（通过tryAdvance）或者成批地，连续地遍历（通过forEachRemaining）
 * 
 * <p>一个spliterator可能隔开它的一些元素（使用trySplit）作为另一个spliterator，用作可能并发的操作。
 * 使用一个不能分割或者以高度不平衡或者低效率的方式分割的spliterator的行为，很可能不会因为并发收益。
 * 遍历和分割耗尽元素，每个spliterator队一个单独的块计算有效
 * 
 * <p>一个spliterator也能报告一个它的结构，来源，元素的特征集（通过characteristics()），包括
 * ordered，distinct，sorted，sized，nonnull，immutable，concurrent，subsized。
 * 这些可能会被spliterator的使用者使用，来控制，特殊化或者简单化计算。
 * 例如，一个collection的spliterator会报告sized，set报告distinct，sorted set报告distinct和sorted
 * 特征集会被以一个简单的bitset的形式被报告。
 * 
 * <p>一些特征集额外地限制方法的行为。例如，如果是ordered，遍历方法必须符合他们表明的有序。
 * 续保的特征集可能会在未来被定义，所以实现类不应该对未被标明的值指派意义。
 * 
 * <p>一个没有报告immutable或者concurrent的spliterator应该有一个文档化的策略：
 * 当spliterator与元素来源绑定，并且对元素来源的结构的干扰会在绑定后被检测到。
 * 一个迟绑定的spliterator在第一次遍历，第一次分割或者第一次对预计大小查询时与元素来源绑定，而不是在spliterator被创建时绑定。
 * 一个不是迟绑定的spliterator在创建或者任何方法的第一次调用时绑定。
 * 在绑定之前对来源的修改会在spliterator遍历时显示出来。
 * 在绑定一个spliterator后，应该基于一个最大努力的假设，如果结构的干扰被检测出，则抛出一个ConcurrentModificationException的错误。
 * 如此做的spliterator被称为fail-fast，快速失败。
 * spliterator的成块遍历的方法（forEachRemaining）可能优化遍历并且在所有元素被遍历完后检查对结构的干扰，而不是遍历每个元素时都检查，然后立即失败。
 * 
 * <p>spliterators 能提供一个预计残留的元素的数目，通过estimatesize方法。
 * 理想上，当体现在特征为sized时，这个值准确地对应元素的多少，那会导致一个完美的遍历。
 * 然而，甚至当没有准确地知道时，一个预估大小的值可能对源头的操作有用，例如帮助决定是继续分割还是连续地遍历剩余的元素哪个更有利。
 * 
 * <p>尽管spliterators明显在并发算法中很实用，但是它们不有被预计为是线程安全的。
 * 相反，使用spliterators的并法算法的实现，应该确保spliterator应该同一时间只被一个线程使用。
 * 这通常很容易达到，通过串行线程封闭，这通常是一个通过递归的分解来工作的典型并发算法的自然结果。
 * 一个调用trysplit的线程可能移交返回的spliterator给另一个线程，它可能轮流遍历这个spliterator或者分割它。
 * 如果两个或以上的线程并发地操作同一个spliterator时，分割或者遍历的行为是不确定的。
 * 如果最初的线程将一个spliterator转交给另一个线程来处理，那么最好在任何元素被tryAdvance消费前传递它，
 * 因为某些保证（例如sized的spliterator的estimatesize方法的准确性）仅仅在遍历开始前有效。
 * 
 * <p>spliterator对基本类（int，long，double）的实现被提供了。
 * 这些子类的默认实现的tryAdvance和forEachRemaining包装了基本值对他们对于的包装类。
 * 这样的包装可能破坏任何通过使用基本类型获得优势的行为。
 * 为了避免包装，对于的基于基本类型的方法应该被使用。
 * 例如OfInt的tryAdvance（IntConsumer）和forEachRemaining（IntConsumer）方法应该被使用，
 * 优先于tryAdvance（Consumer）和forEachRemaining（Consumer）
 * 使用基于包装类的方法（tryAdvance和forEachRemaining）遍历基本值，不影响值转换为包装值的顺序。
 * 
 * <p>spliterators，像iterator，是为了遍历一个来源的元素。
 * spliterator这个api被设计用来提供有效的并发遍历，取代了连续遍历，通过支持分解和单元素迭代。
 * 此外，通过一个spliterator访问元素的协议，被设计用来让每个元素的开销比iterator小，
 * 并且避免有hasNext和next这样的继承的方法
 *
 * <p>对于可更改的来源，随意的和非确定性的行为可能发生，如果来源的结构在spliterator与来源绑定和遍历结束之间，被元素添加，替换，删除等行为干扰。
 * 举个例子，当使用stream框架是，这些行为会产生随意的随意的和非确定性的结果。
 *
 * <p>Structural interference of a source can be managed in the following ways
 * (in approximate order of decreasing desirability):
 * 
 * <p>对来源的结构的干扰能以下面的方法管理（通过降低吸引力的近似顺序）
 * <p>1 来源的结构不能被干扰。比如CopyOnWriteArrayList是个不可更改的来源。
 * 从这种来源产生的spliterator会报告特征immutable
 * <p>2 来源管理并发的修改，比如ConcurrentHashMap是个并发的来源，这种会报告concurrent
 * <p>3 可变的来源提供一个迟绑定的和fail-fast的spliterator。迟绑定缩短了干扰影响计算的窗口期。
 * fail-fast机制以基于最大努力的假设，探测出在遍历开始后的干扰并抛出ConcurrentModificationException
 * 比如，arraylist和许多其他的jdk中的肺病发的类，提供一个迟绑定，fail-fast的spliterator
 * <p>4 可变的来源提供一个非迟绑定，fail-fast的spliterator。
 * 来源增长了抛出ConcurrentModificationException的可能性，因为增加了干扰影响计算的窗口期。
 * <p>5 可变的来源提供一个迟绑定，非fail-fast的spliterator。
 * 这个来源受到遍历开始后进行随意的，非确定性操作的影响，因为干扰没有被检测到。
 * <p>6  可变的来源提供一个非迟绑定，非fail-fast的spliterator。
 * 这个来源增加了随意的，非确定性操作的风险，因为没有被探测到的干扰可能在建造后发生。
 * 
 * 
 * <p>举个例子，下面是一个类（不是很有用，作为例子），它维持着一个数组，里面在偶数位置有真正的数据，
 * 奇数位置有不相关的标签数据。它的spliterator忽视这些标签。
 *
 * <pre> {@code
 * class TaggedArray<T> {
 *   private final Object[] elements; // 数组不可更改
 *   TaggedArray(T[] data, Object[] tags) {
 *     int size = data.length;
 *     if (tags.length != size) throw new IllegalArgumentException();
 *     this.elements = new Object[2 * size];
 *     for (int i = 0, j = 0; i < size; ++i) {
 *       elements[j++] = data[i];
 *       elements[j++] = tags[i];//交替放入数据
 *     }
 *   }
 *
 *   public Spliterator<T> spliterator() {
 *     return new TaggedArraySpliterator<>(elements, 0, elements.length);
 *   }
 *
 *   static class TaggedArraySpliterator<T> implements Spliterator<T> {
 *     private final Object[] array; //这个array就是TaggedArray的elements
 *     private int origin; // 现在的index，用于分割或者遍历
 *     private final int fence; // 栅栏，最大的index（不能到达）
 *
 *     TaggedArraySpliterator(Object[] array, int origin, int fence) {
 *       this.array = array; this.origin = origin; this.fence = fence;
 *       //初始化时是 elements, 0, elements.length
 *     }
 *
 *     public void forEachRemaining(Consumer<? super T> action) {
 *       for (; origin < fence; origin += 2)
 *       //从origin到fence，每次+2，使用action.accept，参数为对应的元素
 *         action.accept((T) array[origin]);
 *     }
 *
 *     public boolean tryAdvance(Consumer<? super T> action) {
 *       if (origin < fence) {
 *       //如果origin<fence，则action处理origin位置上的元素，然后origin+2，返回true
 *         action.accept((T) array[origin]);
 *         origin += 2;
 *         return true;
 *       }
 *       else // 不能用action处理新的元素，则返回false
 *         return false;
 *     }
 *
 *     public Spliterator<T> trySplit() {
 *       int lo = origin; // divide range in half
 *       int mid = ((lo + fence) >>> 1) & ~1; // 让mid为偶数（与11110与操作，前面不变，最后边0，变成偶数）
 *       if (lo < mid) { // 将左半部分分割给调用者，自己处理右半部分
 *         origin = mid; // reset this Spliterator's origin
 *         return new TaggedArraySpliterator<>(array, lo, mid);
 *       }
 *       else       // too small to split
 *         return null;
 *     }
 *
 *     public long estimateSize() {
 *       return (long)((fence - origin) / 2);  //预估剩余处理元素
 *     }
 *
 *     public int characteristics() {
 *       return ORDERED | SIZED | IMMUTABLE | SUBSIZED; //几个元素进行或运算，最后应该是可分割的
 *     }
 *   }
 * }}</pre>
 * 
 * <p>下面是一个并发计算框架，例如stream包，将使用spliterator来并发计算的例子，
 * 下面是一个实现并发关联运算的例子，阐述了基本的使用习惯：分割子任务，直到预估的工作足够小，以至于能够连续处理。
 * 现在我们假设处理子任务的顺序不重要，不同的任务可能更多地并发分割并且处理元素，以不能确定的顺序。
 * 这个例子使用了CountedCompleter，类似的使用方式也应用于其他的并发任务结构。
 *
 * <pre>{@code
 * static <T> void parEach(TaggedArray<T> a, Consumer<T> action) {
 *   Spliterator<T> s = a.spliterator(); //先用TaggedArray创建一个spliterator
 *   long targetBatchSize = s.estimateSize() / (ForkJoinPool.getCommonPoolParallelism() * 8); //预估spliterator的大小/一个数字
 *   new ParEach(null, s, action, targetBatchSize).invoke();
 * }
 *
 * static class ParEach<T> extends CountedCompleter<Void> {
 *   final Spliterator<T> spliterator;
 *   final Consumer<T> action;  
 *   final long targetBatchSize;  //每次处理元素的多少
 *
 *   ParEach(ParEach<T> parent, Spliterator<T> spliterator,
 *           Consumer<T> action, long targetBatchSize) {
 *     super(parent);
 *     this.spliterator = spliterator; this.action = action;
 *     this.targetBatchSize = targetBatchSize;
 *   }
 *
 *   public void compute() {
 *     Spliterator<T> sub;
 *     while (spliterator.estimateSize() > targetBatchSize &&
 *            (sub = spliterator.trySplit()) != null) {
 *            //如果spliterator的estimateSize>targetBatchSize并且spliterator通过trySplit返回的sub不为空
 *       addToPendingCount(1); 调用addToPendingCount
 *       new ParEach<>(this, sub, action, targetBatchSize).fork(); 
 *       //创建新的运行任务ParEach，将sub放进去（第一次是一半，第二次是1/4，直到剩余元素小于targetBatchSize）
 *     }
 *     spliterator.forEachRemaining(action); //spliterator处理剩余的元素，此时剩余元素小于targetBatchSize
 *     propagateCompletion(); //完成任务
 *   }
 * }}</pre>
 *
 * <p> 如果tripwire的系统boolean变量被设置成true，如果当操作基本子类型时，会发生基本类型的包装，然后会报告诊断的错误
 *
 * @param <T> the type of elements returned by this Spliterator
 *
 * @see Collection
 * @since 1.8
 */
public interface Spliterator<T> {
    /**
     * <p>如果剩余一个元素，使用给定的action执行它，返回true，否则返回false
     * <p>如果这个spliterator是ordered的，这个action按照相遇的顺序，对下一个元素进行操作
     * <p>异常抛出给调用者
     * 
     * @param action The action
     * @return {@code false} if no remaining elements existed
     * upon entry to this method, else {@code true}.
     * @throws NullPointerException if the specified action is null
     */
    boolean tryAdvance(Consumer<? super T> action);

    /**
     * 
     * <p>在当前线程，以连续的顺序，对每个剩余的元素执行给定的操作，直到所有元素已经被处理或者操作抛出异常。
     * 如果这个spliterator是ordered的，操作以遇到的顺序执行。异常抛出给调用者。
     * <p>默认实现重复调用tryAdvance直到它返回false。如果有需要时应该被覆盖。
     *
     *
     * @param action The action
     * @throws NullPointerException if the specified action is null
     */
    default void forEachRemaining(Consumer<? super T> action) {
        do { } while (tryAdvance(action));
    }

    /**
     * <p>如果这个spliterator能够被分割，返回一个spliterator，
     * 它能包含一部分元素，能这部分就不会被这个spliterator包含。
     * 
     * <p>如果这个spliterator是ordered的，返回的spliterator必须包含有严格前缀的元素
     * 
     * <p>除非这个spliterator包含无限的元素，重复地调用trySplit一定会最后返回null，之前返回非null
     * 
     * <p>在分割前estimateSize方法返回的值必须大于等于分割后estimateSize方法返回的值。
     * 
     * <p>如果这个spliterator是subsized的，在分割前estimateSize方法返回的值必须等于分割后estimateSize方法返回的值
     * 
     * <p>这个方法可能因为一些原因返回null，包括元素为空，遍历开始后不能分割，数据结构的限制和出于效率的考虑
     * 
     * <p>一个理想的trySplit方法有效地（不包括遍历）恰好分割了它一半的元素，从而允许平衡的并发计算。
     * 许多背离了这个理想保持着高度的有效。
     * 比如，仅仅大约地分割一个大约平衡的树或者一个叶子节点仅包含1个或2个元素的树不能继续分割这些节点。
     * 然而，巨大的偏离平衡或者非常无效的trySplit结构会典型地导致非常差的并发效果
     * 
     *
     * @return a {@code Spliterator} covering some portion of the
     * elements, or {@code null} if this spliterator cannot be split
     */
    Spliterator<T> trySplit();

    /**
     * 
     * <p>返回一个根据forEachRemaining遍历会遇到的元素的个数或者如果元素是无限的，未知的，计算太昂贵的，返回long的max_value
     * 
     * <p>如果这个spliterator是sized的，并且没有被部分遍历过或者分割，或者这个spliterator是subsized并且没有被部分遍历过，
     * 这个估计必须是个准确的通过一次完整的遍历会遇到的元素的个数。
     * 然而，这个估计可能是不准确的，但经过调用trySplit，一定会降低。
     * 
     * <p>甚至一个不准确的估计也是有用的并且计算起来不昂贵。
     * 比如，一个大概平衡的二叉树的子spliterator可能返回一个值，这个值是它的父spliterator返回的一半。
     * 如果根spliterator没有保存准确的数目，它能估计的大小是2的它的最大深度次方。
     * 
     *
     * @return the estimated size, or {@code Long.MAX_VALUE} if infinite,
     *         unknown, or too expensive to compute.
     */
    long estimateSize();

    /**
     * 
     * <p>如果spliterator是sized的，就返回estimateSize的结果（这个是准确的数量），否则返回-1。
     * 默认的方法就是这样干的。
     * 
     * @return the exact size, if known, else {@code -1}.
     */
    default long getExactSizeIfKnown() {
        return (characteristics() & SIZED) == 0 ? -1L : estimateSize();
    }

    /** 
     * <p>返回这个spliterator的元素的特征的集合。
     * 结果被表达成ORDERED，DISTINCT，SORTED，SIZED，NONNULL，IMMUTABLE，CONCURRENT，SUBSIZED的或值。
     * 在trySplit前或者两个trySplit之前重复调用characteristics应该总是返回相同的结果。
     * 
     * <p>如果一个spliterator报告一个不一致的特征集合（不管返回给一个调用或者多个调用），使用这个spliterator不能保证任何计算
     * 
     * <p>一个spliterator的特征在分割前和分割后可能不同。典型的例子是sized，subsized，concurrent
     *
     * @return a representation of characteristics
     */
    int characteristics();

    /**
     * 
     * <p>如果这个spliterator包含了给定的所有特征，返回true
     * 默认的实现，如果给定的特征的位被设定了，就返回true
     *
     * @param characteristics the characteristics to check for
     * @return {@code true} if all the specified characteristics are present,
     * else {@code false}
     */
    default boolean hasCharacteristics(int characteristics) {
        return (characteristics() & characteristics) == characteristics;
        //自己的特征&给的特征，如果自己的在给的之中，则比如会返回自己的特征
    }

    /**
     * <p>如果spliterator的来源是sorted，通过一个comparator，则返回这个comparator。
     * 如果来源是sorted，以自然地顺序，返回null。
     * 然而，如果来源不是sorted，抛出IllegalStateException。
     * 
     * <p>默认实现总是抛出IllegalStateException。
     * 
     *
     * @return a Comparator, or {@code null} if the elements are sorted in the
     * natural order.
     * @throws IllegalStateException if the spliterator does not report
     *         a characteristic of {@code SORTED}.
     */
    default Comparator<? super T> getComparator() {
        throw new IllegalStateException();
    }

    /**
     * 
     * <p> 特征值，代表着为元素定义了一个相遇的顺序。如果这样，spliterator保证trySplit严格地按照元素的前缀分割。
     * tryAdvance以前缀的顺序，一次前进一个元素。forEachRemaining以相遇的顺序执行操作。
     * 
     * <p>一个Collection有一个相遇的顺序，如果对应的iterator报告有顺序。
     * 如果这样，相遇的顺序和报告的顺序相同。否则，一个collection确实没有一个相遇的顺序。
     * 
     * <p>对于任何list，相遇舜玉被保证是上升的index顺序。但是对于基于哈希的collection，例如hashset，不能保证顺序。
     * 一个ordered的spliterator的用户，希望在非交替的并发的计算中，保持顺序的限制
     * 
     */
    public static final int ORDERED    = 0x00000010;

    /**
     * 
     * <p> 特征值，代表着spliterator的所有元素，两两使用x.equals(y) 都为false，意味着它们没有一个相同。
     * 这个请求，举个例子，对于一个基于set的spliterator。
     */
    public static final int DISTINCT   = 0x00000001;

    /**
     * 
     * <p>特征值，代表着相遇顺序遵循着一个定义过的排序顺序。如果这样，getComparator返回一个关联的comparator，
     * 或者如果所有元素是comparable并且以自然的顺序排序，返回null。
     * 
     * <p>一个sorted的spliterator必须也是ordered的。
     * 
     * <p>jdk中的实现navigableset或者sortedset的collecion，的spliterator，是sorted的
     */
    public static final int SORTED     = 0x00000004;

    /**
     * 
     * <p>特征值，代表着在遍历或者分割前返回的estimateSize代表了一个有限的大小，
     * 无视了数据结构来源的变动，代表了一次完整遍历会遇到的准确数字。
     * 
     * <p>collection的大部分spliterator，如果有这个特征，包含了它所有的元素。
     * 子spliterator，例如hashset，包含了元素的一个子集并且近似于它们报告的大小。
     */
    public static final int SIZED      = 0x00000040;

    /**
     * <p>特征值，代表着这个来源保证相遇的所有元素不会为null。
     * 例如，这适用于大部分collections,queues,map
     */
    public static final int NONNULL    = 0x00000100;

    /**
     * <p>特征值，代表着元素来源的结构不能被改变。元素不能被添加，代替，删除，在遍历过程中，这些改变不能发生。
     * 一个不是immutable或者concurrent被希望有一个文档化的政策（例如抛出ConcurrentModificationException）
     * 当在遍历中涉及到探测出结构的干扰。
     */
    public static final int IMMUTABLE  = 0x00000400;

    /**
     * 
     * <p>特征值，代表着元素的来能可能被安全地，并发地修改，（允许增加，代替，和/或者删除）通过没有多余同步的多线程。
     * 如果这样，spliterator被期待有一个文档化的策略，关于在遍历中修改的影响。
     * 
     * <p>一个最高层的spliterator应该不同时是concurrent和sized的，
     * 因为有限的大小（如果已知），可能在遍历中并发地修改时，大小变化。
     * 这样的spliterator是不一致的，并且不能保证任何使用这个spliterator的计算。
     * 子spliterator可能是sized，如果分割后的大小是已知的，并且当遍历时，对来源的增加或删除不会反应到遍历中。
     * 
     * <p>大部分并发的集合有一个一致性策略，保证在spliterator创建时元素的准确性，但可能不会反应出后来的增加或者删除。
     */
    public static final int CONCURRENT = 0x00001000;

    /**
     * <p>特征值，代表着所有的通过trySplit产生的spliterator都是sized和subsized。
     * 这意味着所有的子spliterator，无论是亲的或者不亲的，都是sized的。
     * 
     * <p>如果一个spliterator没有按照subsized，报告sized，
     * 那它是不一致的，并且不能保证使用这个spliterator做出的任何计算。
     * 
     * <p>一些spliterator，例如对一颗接近平衡的二叉树的顶级spliterator，是sized，但不是subsized，
     * 因为很容易知晓整棵树的大小，但不知道子树的具体大小。
     */
    public static final int SUBSIZED = 0x00004000;

    /**
     * 一个专门为基本类型的spliterator
     *
     * @param <T> 被这个spliterator返回的元素的类型。这个类型必须是一个基本类型的包装类，例如Integer对于基本类型int。
     * 
     * @param <T_CONS> 原始的conumser的类型。这个类型必须是对T的consumer类的基本实例。例如IntConsumer对于Integer、
     * 
     * @param <T_SPLITR> 基本spliterator的类型。这个类型必须是对T的spliterator的基本实例，例如Spliterator.OfInt对于Integer
     * 
     * <p>这个类里重写了trySplit，返回T_SPLITR类型的spliterator。
     * 
     * <p>还增加了两个方法tryAdvance,forEachRemaining，里面的参数为T_CONS
     *
     * @see Spliterator.OfInt
     * @see Spliterator.OfLong
     * @see Spliterator.OfDouble
     * @since 1.8
     */
    public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
            extends Spliterator<T> {
        @Override
        T_SPLITR trySplit();

        /**
         * If a remaining element exists, performs the given action on it,
         * returning {@code true}; else returns {@code false}.  If this
         * Spliterator is {@link #ORDERED} the action is performed on the
         * next element in encounter order.  Exceptions thrown by the
         * action are relayed to the caller.
         *
         * @param action The action
         * @return {@code false} if no remaining elements existed
         * upon entry to this method, else {@code true}.
         * @throws NullPointerException if the specified action is null
         */
        @SuppressWarnings("overloads")
        boolean tryAdvance(T_CONS action);

        /**
         * Performs the given action for each remaining element, sequentially in
         * the current thread, until all elements have been processed or the
         * action throws an exception.  If this Spliterator is {@link #ORDERED},
         * actions are performed in encounter order.  Exceptions thrown by the
         * action are relayed to the caller.
         *
         * @implSpec
         * The default implementation repeatedly invokes {@link #tryAdvance}
         * until it returns {@code false}.  It should be overridden whenever
         * possible.
         *
         * @param action The action
         * @throws NullPointerException if the specified action is null
         */
        @SuppressWarnings("overloads")
        default void forEachRemaining(T_CONS action) {
            do { } while (tryAdvance(action));
        }
    }

    /**
     * 一个对int的专门的spliterator
     * @since 1.8
     */
    public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> {
    	
    	//下面的这三个方法就是如OfPrimitive覆盖的那三个方法。

        @Override
        OfInt trySplit();

        @Override
        boolean tryAdvance(IntConsumer action);

        @Override
        default void forEachRemaining(IntConsumer action) {
            do { } while (tryAdvance(action));
        }

        /** 
         * 如果这个action是IntConsumer的实例，将它转为IntConsumer并且转为调用tryAdvance(IntConsumer)方法。
         * 否则这个action会被适配为IntConsumer的实例，通过包装IntConsumer的参数，然后传递给IntConsumer。
         */
        @Override
        default boolean tryAdvance(Consumer<? super Integer> action) {
            if (action instanceof IntConsumer) {
                return tryAdvance((IntConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfInt.tryAdvance((IntConsumer) action::accept)");
                return tryAdvance((IntConsumer) action::accept);
            }
        }

        /**
         * {@inheritDoc}
         * @implSpec
         * If the action is an instance of {@code IntConsumer} then it is cast
         * to {@code IntConsumer} and passed to
         * {@link #forEachRemaining(java.util.function.IntConsumer)}; otherwise
         * the action is adapted to an instance of {@code IntConsumer}, by
         * boxing the argument of {@code IntConsumer}, and then passed to
         * {@link #forEachRemaining(java.util.function.IntConsumer)}.
         */
        @Override
        default void forEachRemaining(Consumer<? super Integer> action) {
            if (action instanceof IntConsumer) {
                forEachRemaining((IntConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfInt.forEachRemaining((IntConsumer) action::accept)");
                forEachRemaining((IntConsumer) action::accept);
            }
        }
    }

    /**
     * A Spliterator specialized for {@code long} values.
     * @since 1.8
     */
    public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> {

        @Override
        OfLong trySplit();

        @Override
        boolean tryAdvance(LongConsumer action);

        @Override
        default void forEachRemaining(LongConsumer action) {
            do { } while (tryAdvance(action));
        }

        /**
         * {@inheritDoc}
         * @implSpec
         * If the action is an instance of {@code LongConsumer} then it is cast
         * to {@code LongConsumer} and passed to
         * {@link #tryAdvance(java.util.function.LongConsumer)}; otherwise
         * the action is adapted to an instance of {@code LongConsumer}, by
         * boxing the argument of {@code LongConsumer}, and then passed to
         * {@link #tryAdvance(java.util.function.LongConsumer)}.
         */
        @Override
        default boolean tryAdvance(Consumer<? super Long> action) {
            if (action instanceof LongConsumer) {
                return tryAdvance((LongConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfLong.tryAdvance((LongConsumer) action::accept)");
                return tryAdvance((LongConsumer) action::accept);
            }
        }

        /**
         * {@inheritDoc}
         * @implSpec
         * If the action is an instance of {@code LongConsumer} then it is cast
         * to {@code LongConsumer} and passed to
         * {@link #forEachRemaining(java.util.function.LongConsumer)}; otherwise
         * the action is adapted to an instance of {@code LongConsumer}, by
         * boxing the argument of {@code LongConsumer}, and then passed to
         * {@link #forEachRemaining(java.util.function.LongConsumer)}.
         */
        @Override
        default void forEachRemaining(Consumer<? super Long> action) {
            if (action instanceof LongConsumer) {
                forEachRemaining((LongConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfLong.forEachRemaining((LongConsumer) action::accept)");
                forEachRemaining((LongConsumer) action::accept);
            }
        }
    }

    /**
     * A Spliterator specialized for {@code double} values.
     * @since 1.8
     */
    public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> {

        @Override
        OfDouble trySplit();

        @Override
        boolean tryAdvance(DoubleConsumer action);

        @Override
        default void forEachRemaining(DoubleConsumer action) {
            do { } while (tryAdvance(action));
        }

        /**
         * {@inheritDoc}
         * @implSpec
         * If the action is an instance of {@code DoubleConsumer} then it is
         * cast to {@code DoubleConsumer} and passed to
         * {@link #tryAdvance(java.util.function.DoubleConsumer)}; otherwise
         * the action is adapted to an instance of {@code DoubleConsumer}, by
         * boxing the argument of {@code DoubleConsumer}, and then passed to
         * {@link #tryAdvance(java.util.function.DoubleConsumer)}.
         */
        @Override
        default boolean tryAdvance(Consumer<? super Double> action) {
            if (action instanceof DoubleConsumer) {
                return tryAdvance((DoubleConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfDouble.tryAdvance((DoubleConsumer) action::accept)");
                return tryAdvance((DoubleConsumer) action::accept);
            }
        }

        /**
         * {@inheritDoc}
         * @implSpec
         * If the action is an instance of {@code DoubleConsumer} then it is
         * cast to {@code DoubleConsumer} and passed to
         * {@link #forEachRemaining(java.util.function.DoubleConsumer)};
         * otherwise the action is adapted to an instance of
         * {@code DoubleConsumer}, by boxing the argument of
         * {@code DoubleConsumer}, and then passed to
         * {@link #forEachRemaining(java.util.function.DoubleConsumer)}.
         */
        @Override
        default void forEachRemaining(Consumer<? super Double> action) {
            if (action instanceof DoubleConsumer) {
                forEachRemaining((DoubleConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfDouble.forEachRemaining((DoubleConsumer) action::accept)");
                forEachRemaining((DoubleConsumer) action::accept);
            }
        }
    }
}
